package dpe;

import java.io.File;
import java.io.FileInputStream;
import java.util.Properties;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class EngineLoader {
	private Engine engine;
	private Game game;

	public EngineLoader(Engine e) {
		engine = e;
	}

	public void loadFile(File file) {
		if (!file.getName().endsWith(Engine.FILE_EXTENSION)) {
			Engine.log(2, "Could not read file '" + file.getName() + "': Unknown file type");
			Engine.exit(1);
		}
		if (!file.exists()) {
			Engine.log(2, "Could not find file '" + file.getName() + "'");
			Engine.exit(1);
		}
		try {
			Engine.log(0, "Reading file '" + file.getName() + "'");
			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
			DocumentBuilder builder = factory.newDocumentBuilder();
			Document document = builder.parse(file);
			document.getDocumentElement().normalize();

			String fileType = document.getDocumentElement().getNodeName();
			if (fileType.toLowerCase().equals("game")) {
				Game game = engine.newGame();
				if (document.getDocumentElement().hasAttribute("properties")) {
					File propertiesFile = new File(document.getDocumentElement().getAttribute("properties"));
					loadGameProperties(game, propertiesFile);
				}

				this.game = game;

				NodeList nodelist = document.getDocumentElement().getElementsByTagName("world");
				for (int i = 0; i < nodelist.getLength(); i++) {
					Node n = nodelist.item(i);

					if (n.getNodeType() == Node.ELEMENT_NODE) {
						Element e = (Element) n;
						if (e.hasAttribute("src")) {
							loadFile(new File(e.getAttribute("src")));
						} else {
							Engine.log(2, "No src in world tag");
							Engine.exit(1);
						}
					}
				}
				engine.startGame();
			} else if (fileType.toLowerCase().equals("world")) {
				Element e = document.getDocumentElement();
				String name = e.getAttribute("name");
				World world = new World(game, name);
				if (e.hasAttribute("properties")) {
					File propertiesFile = new File(e.getAttribute("properties"));
					loadWorldProperties(world, propertiesFile);
				}

				NodeList nodelist = document.getDocumentElement().getElementsByTagName("object");
				for (int i = 0; i < nodelist.getLength(); i++) {
					Node n = nodelist.item(i);

					if (n.getNodeType() == Node.ELEMENT_NODE) {
						Element ce = (Element) n;
						String objectName = "", type = "";
						Vec3 pos = new Vec3();
						Vec3 size = new Vec3();
						if (ce.hasAttribute("name")) {
							objectName = ce.getAttribute("name");
						}
						if (ce.hasAttribute("type")) {
							type = ce.getAttribute("type").toLowerCase();
						}
						if (ce.hasAttribute("posx")) {
							pos.x = Integer.parseInt(ce.getAttribute("posx"));
						}
						if (ce.hasAttribute("posy")) {
							pos.x = Integer.parseInt(ce.getAttribute("posy"));
						}
						if (ce.hasAttribute("posz")) {
							pos.x = Integer.parseInt(ce.getAttribute("posz"));
						}
						if (ce.hasAttribute("sizex")) {
							size.x = Integer.parseInt(ce.getAttribute("sizex"));
						}
						if (ce.hasAttribute("sizey")) {
							size.x = Integer.parseInt(ce.getAttribute("sizey"));
						}
						if (ce.hasAttribute("sizez")) {
							size.x = Integer.parseInt(ce.getAttribute("sizez"));
						}
						if (type.equals("player")) {
							Player p = new Player(world, objectName, pos);
							world.addObject(p);
						} else if (type.equals("camera")) {
							Camera c = new Camera(world, objectName, pos);
							world.addObject(c);
						} else if (type.equals("box")) {
							Box b = new Box(world, objectName, pos, size);
							world.addObject(b);
						}
					}
				}

				game.addWorld(world);
			}
			engine.init();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void loadObjectProperties(GameObject object, File file) {
		Engine.log(0, "Reading properties '" + file.getName() + "' for object '" + object.getName() + "'");
		FileInputStream inputStream;
		try {
			inputStream = new FileInputStream(file);
			Properties properties = new Properties();
			properties.load(inputStream);
			inputStream.close();

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void loadWorldProperties(World world, File file) {
		Engine.log(0, "Reading properties '" + file.getName() + "' for world '" + world.getName() + "'");
		FileInputStream inputStream;
		try {
			inputStream = new FileInputStream(file);
			Properties properties = new Properties();
			properties.load(inputStream);
			inputStream.close();

			if (properties.getProperty("setplayer") != null) {
				String name = properties.getProperty("setplayer");
				world.setPlayer(name);
			}

			if (properties.getProperty("setcamera") != null) {
				String name = properties.getProperty("setcamera");
				world.setCamera(name);
			}

		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	public void loadGameProperties(Game game, File file) {
		Engine.log(0, "Reading properties '" + file.getName() + "' for game");
		FileInputStream inputStream;
		try {
			inputStream = new FileInputStream(file);
			Properties properties = new Properties();
			properties.load(inputStream);
			inputStream.close();

			if (properties.getProperty("windowwidth") != null) {
				int w = Integer.parseInt(properties.getProperty("windowwidth"));
				game.setWindowWidth(w);
			}

			if (properties.getProperty("windowheight") != null) {
				int h = Integer.parseInt(properties.getProperty("windowheight"));
				game.setWindowHeight(h);
			}

			if (properties.getProperty("windowtitle") != null) {
				String t = properties.getProperty("windowtitle");
				game.setWindowTitle(t);
			}

			if (properties.getProperty("world") != null) {
				String t = properties.getProperty("windowtitle");
				game.setStartWorld(t);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

	}
}
